package com.starhub.domain.annotate.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.starhub.application.agent.dto.AIChatInfo;
import com.starhub.application.agent.result.AiChatResult;
import com.starhub.application.agent.service.IChatService;
import com.starhub.application.collection.dto.MetaDataLinkDto;
import com.starhub.application.collection.entity.KnowledgeCollection;
import com.starhub.application.collection.enums.CollectionTypeEnums;
import com.starhub.application.collection.service.DataManipulationService;
import com.starhub.application.collection.service.KnowledgeCollectionService;
import com.starhub.application.collection.service.KnowledgeItemService;
import com.starhub.application.model.util.TokenUtil;
import com.starhub.application.rag.constant.RagConstant;
import com.starhub.application.rag.service.MilvusFlushService;
import com.starhub.domain.annotate.builder.ChatInfoBuilder;
import com.starhub.domain.annotate.client.DataFormatClient;
import com.starhub.domain.annotate.component.FormatComponent;
import com.starhub.domain.annotate.dto.DataAnnotatePrompt;
import com.starhub.domain.annotate.dto.DataAnnotateRequest;
import com.starhub.domain.annotate.enums.UseTypeEnums;
import com.starhub.domain.annotate.service.DataAnnotateService;
import com.starhub.domain.knowledge.entity.KnowledgeItem;
import com.starhub.domain.knowledge.service.KnowledgeService;
import com.starhub.domain.knowledge.vo.KnowledgeItemVo;
import com.starhub.utils.Util;

import lombok.extern.slf4j.Slf4j;

/**
 * 数据标注服务实现类
 * 
 * @version: V1.0
 * @author: liuhf
 * @time 2025-06-18
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class DataAnnotateServiceImpl implements DataAnnotateService {

    @Autowired
    private IChatService chatService;

    @Autowired
    private ChatInfoBuilder chatInfoBuilder;

    @Autowired
    private KnowledgeCollectionService knowledgeCollectionService;

    @Autowired
    private KnowledgeService knowledgeService;

    @Autowired  
    private FormatComponent formatComponent;

    @Autowired
    private DataManipulationService dataManipulationService;

    @Autowired
    private KnowledgeItemService knowledgeItemService;

    @Autowired  
    private MilvusFlushService milvusFlushService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean autoAnnotation(DataAnnotateRequest dataAnnotationDto) {
        try {
            log.info("开始自动标注，请求参数: {}", dataAnnotationDto);
            
            // 获取知识内容
            KnowledgeItemVo item = knowledgeService.getKnowledgeItemById(Util.getLongValue(dataAnnotationDto.getDataId()));
            if (item == null) {
                log.error("知识内容不存在，id: {}", dataAnnotationDto.getDataId());
                throw new RuntimeException("知识内容不存在");
            }   

            // 获取知识库和元知识库
            KnowledgeCollection knowledgeCollection = knowledgeCollectionService
                    .selectById(Util.getLongValue(dataAnnotationDto.getCollectionId()));
            KnowledgeCollection metaKnowledgeCollection = knowledgeCollectionService
                    .selectById(Util.getLongValue(dataAnnotationDto.getMetaCollectionId()));

            if (knowledgeCollection == null || metaKnowledgeCollection == null) {
                log.error("知识库或元知识库不存在，collectionId: {}, metaCollectionId: {}", 
                         dataAnnotationDto.getCollectionId(), dataAnnotationDto.getMetaCollectionId());
                throw new RuntimeException("知识库或元知识库不存在");
            }
            
            if (knowledgeCollection.getBusinessType() != CollectionTypeEnums.MAIN_DATA.getCode()
                    || metaKnowledgeCollection.getBusinessType() != CollectionTypeEnums.META_DATA.getCode()) {
                log.error("知识库类型错误，mainData type: {}, metaData type: {}", 
                         knowledgeCollection.getBusinessType(), metaKnowledgeCollection.getBusinessType());
                throw new RuntimeException("知识库类型错误");
            }

            // 处理提示词相关信息
            DataFormatClient dataFormatClient = formatComponent.getClient(UseTypeEnums.getFormatDataByCode(metaKnowledgeCollection.getUseType()));
            String metaRealData = "";//dataFormatClient.getData(dataAnnotationDto.getCollectionId());

            List<String> metaRealDataList = knowledgeItemService.getAllDatas(Util.getLongValue(dataAnnotationDto.getMetaCollectionId()));
            metaRealData = String.join("\n", metaRealDataList);

            int metaRealDataTokens = TokenUtil.calculateTokensByChar(metaRealData);
            /*
            TODO: 数据量过大时自动标注超token的处理，暂时不限制元知识库数据量
            if(metaRealDataTokens > 10000){
                log.error("元知识库数据量过大，无法进行标注，数据量: {}", metaRealDataTokens);
                throw new RuntimeException("元知识库数据量过大，无法进行标注，数据量: " + metaRealDataTokens);
            }*/

            AIChatInfo chatInfo = chatInfoBuilder.buildChatInfo(DataAnnotatePrompt.builder()
                    .mainRole(knowledgeCollection.getPromptSegment())
                    .mainName(knowledgeCollection.getName())
                    .metaRole(metaKnowledgeCollection.getPromptSegment())
                    .metaName(metaKnowledgeCollection.getName())
                    .otherRole(UseTypeEnums.getPromptByCode(metaKnowledgeCollection.getUseType()).replace("{metaName}",
                            metaKnowledgeCollection.getName()))
                    .metaRealData(metaRealData)
                    .formatData(UseTypeEnums.getFormatDataByCode(metaKnowledgeCollection.getUseType()).getFormatData())
                    .mainContent(item.getContent())
                    .build());

            // 调用AI服务进行标注
            AiChatResult aiChatResult = chatService.chat(chatInfo);
            String message = aiChatResult.getMessage();
            if (message == null || message.isEmpty()) {
                log.error("AI标注失败，返回结果为空");
                throw new RuntimeException("标注失败");
            }

            log.info("AI标注成功，结果: {}", message);
            // 格式化数据并跟库中的内容进行匹配，返回匹配到的数据ID列表
            List<String> dataList = dataFormatClient.formatData(dataAnnotationDto.getMetaCollectionId(), message);
            
            // 处理标注结果
            dataManipulationService.addTargetLinkData(MetaDataLinkDto.builder()
                    .collectionId(dataAnnotationDto.getCollectionId())
                    .collectionIdentifier(knowledgeCollection.getCollectionIdentifier())
                    .metaCollectionId(dataAnnotationDto.getMetaCollectionId())
                    .metaCollectionIdentifier(metaKnowledgeCollection.getCollectionIdentifier())
                    .baseId(Util.null2String(knowledgeCollection.getBaseId()))
                    .itemId(dataAnnotationDto.getDataId())
                    .selectIds(dataList)
                    .build());
            
            // 刷新元知识库
            milvusFlushService.flushCollection(metaKnowledgeCollection.getCollectionIdentifier());

            // 刷新关联库库
            milvusFlushService.flushCollection(knowledgeCollection.getCollectionIdentifier() + RagConstant.META_POSTFIX);

            log.info("自动标注完成，处理了 {} 条数据", dataList.size());
            return true;
            
        } catch (Exception e) {
            log.error("自动标注失败", e);
            throw new RuntimeException("自动标注失败: " + e.getMessage(), e);
        }
    }
}
